/**
 * createby : JinxLbj
 * date : 2018/8/8
 * desc : 项目服务实现类
 **/

package com.example.demo.biz.project.service.impl;

import com.example.demo.biz.project.service.ProjectService;
import com.example.demo.common.entity.Result;
import com.example.demo.common.enums.FileEnum;
import com.example.demo.common.enums.ResultEnum;
import com.example.demo.common.service.ProcessService;
import com.example.demo.common.thread.ProcessThread;
import com.example.demo.common.utils.SFTPChannel;
import com.example.demo.core.bean.ConfigBean;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.List;

@Service
public class ProjectServiceImpl implements ProjectService {

    private static int WITHOUT_BUILD = 0;
    private static int AFTER_BUILD = 1;

    private static int NPM = 0;
    private static int YARN = 1;

    @Autowired
    private ProcessService processServiceImpl;

    @Autowired
    private ConfigBean configBean;

    @Autowired
    private SFTPChannel sftpChannel;

    @Override
    public Result cloneProject(String projectName, String url, String username, String password) {
        if(username == null || "".equals(username)){
            username = "";
            password = "";
        }
        File path = new File(configBean.PROJECT_HOUSE + projectName);
        try {

            //判断路径是否存在（应该不存在，防止clone抛出文件夹不为空的异常）
            boolean pathexist = path.exists();
            if (!pathexist) {
                //创建文件夹
                pathexist = path.mkdirs();
                //再次判断是否创建成功，防止创建失败
                if (!pathexist) {
                    return Result.buildResult(FileEnum.PATH_ERROR, null);
                }
            } else {
                return Result.buildResult(FileEnum.PATH_ALREADY_EXIST, null);
            }
            CloneCommand cloneCommand = Git.cloneRepository();
            //设置网络仓库路径，本地仓库路径，用户名与密码
            cloneCommand.setURI(url);
            cloneCommand.setDirectory(path);
            cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
            cloneCommand.call();
            return Result.buildResult(FileEnum.PROJECT_CLONE_SUCCESS, "Clone from "
                    + url
                    + " to "
                    + configBean.PROJECT_HOUSE + projectName +
                    " successfully !");
        } catch (GitAPIException e) {
            path.delete();
            if (e.getMessage().contains("not authorized")) {
                return Result.buildResult(FileEnum.AUTH_ERROR, e.getLocalizedMessage());
            }
            return Result.buildResult(FileEnum.UNKNOWN_ERROR, e.getStackTrace());
        }

    }

    @Override
    public Result pullProject(String projectName, String branchName, String remoteName, String username, String password) {
        File path = new File(configBean.PROJECT_HOUSE + projectName + File.separator + ".git");
        //判断项目是否存在
        if (!path.exists()) {
            return Result.buildResult(FileEnum.PROJECT_NOT_EXIST, null);
        }
        try {
            Git git = Git.open(path);
            PullCommand pullCommand = git.pull();
            if (remoteName == null || "".equals(remoteName)) {
                pullCommand.setRemote("origin");
            } else {
                pullCommand.setRemote(remoteName);
            }
            //设置分支
            if (branchName == null || "".equals(branchName)) {
                pullCommand.setRemoteBranchName("master");
            } else {
                pullCommand.setRemoteBranchName(branchName);
            }
            pullCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
            pullCommand.call();
        } catch (IOException | GitAPIException e) {
            if (e.getMessage().contains("not authorized")) {
                return Result.buildResult(FileEnum.AUTH_ERROR, e.getLocalizedMessage());
            } else if (e.getMessage().contains("Ref may not exist")) {
                return Result.buildResult(FileEnum.BRANCH_NOT_EXIST, e.getLocalizedMessage());
            }
            e.printStackTrace();
        }

        return Result.buildResult(FileEnum.PROJECT_PULL_SUCCESS, null);
    }

    @Override
    public Result runProjectBack(String projectName, Integer type, String config, String packageName) {
        if(type == null){
            type = AFTER_BUILD;
        }
        String result = "";
        String command = "";
        String runCommand = "";
        if (type == AFTER_BUILD) {
            command =
                    "cd " + configBean.PROJECT_HOUSE + projectName + " &&" +
                            " mvn clean package &&" +
                            " cd " + configBean.PROJECT_HOUSE + projectName + File.separator + "target &&" +
                            " java -jar " + packageName + " " + config;
            runCommand = "java -jar " + packageName + " " + config;
        }
        if (type == WITHOUT_BUILD) {
            command =
                    "cd " + configBean.PROJECT_HOUSE + projectName + File.separator + "target &&" +
                            " java -jar " + packageName + " " + config;
            runCommand = "java -jar " + packageName + " " + config;
        }
        //放入进程组
        ProcessThread processThread = new ProcessThread(command, projectName, runCommand);
        processThread.start();
        return Result.buildResult(FileEnum.PROJECT_PULL_SUCCESS, result);
    }

    @Override
    public Result runProjectFront(String projectName, Integer type) {
        if (type == null){
            type = AFTER_BUILD;
        }
        String result = "";
        String command = "";
        if (type == NPM) {
            command =
                    "cd " + configBean.PROJECT_HOUSE + projectName + " &&" +
                            " npm install && npm run build ";
        }
        if (type == YARN) {
            command =
                    "cd " + configBean.PROJECT_HOUSE + projectName + " &&" +
                            " yarn install && yarn run build ";
        }
        //放入进程组
        ProcessThread processThread = new ProcessThread(command, projectName, null);
        processThread.start();
        return Result.buildResult(FileEnum.PROJECT_PULL_SUCCESS, result);
    }

    @Override
    public Result stopProject(String projectName) {
        if (projectName == null || "".equals(projectName)) {
            return Result.buildResult(ResultEnum.PARAM_NULL, null);
        }
        boolean flag = processServiceImpl.killProcess(projectName);
        if (flag) {
            return Result.buildResult(ResultEnum.SUCCESS, projectName + "已被停止");
        } else {
            return Result.buildResult(FileEnum.UNKNOWN_ERROR, "终止失败");
        }
    }

    @Override
    public Result uploadProject(String host, Integer port, String ftpUsername, String ftpPassword, String dst, String projectName) {
        try {
            //初始化传输协议并建立根文件夹（最底层的父文件夹必须存在）
            sftpChannel.init(host,
                    port == null ? 22 : port,
                    ftpUsername,
                    ftpPassword,
                    dst);
            System.out.println(">> 传输开始");
            sftpChannel.upload(configBean.PROJECT_HOUSE + projectName + File.separator + "dist",
                    dst);
            System.out.println(">> 传输完成");
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }

        return Result.buildResult(ResultEnum.SUCCESS, null);
    }

    @Override
    public Result uploadProjectBackEnd(String host, Integer port, String ftpUsername, String ftpPassword, String dst, String projectName) {
        try {
            //初始化传输协议并建立根文件夹（最底层的父文件夹必须存在）
            sftpChannel.init(host,
                    port == null ? 22 : port,
                    ftpUsername,
                    ftpPassword,
                    dst);
            System.out.println(">> 传输开始");
            sftpChannel.upload(configBean.PROJECT_HOUSE + projectName + File.separator + "target",
                    dst);
            System.out.println(">> 传输完成");
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }

        return Result.buildResult(ResultEnum.SUCCESS, null);
    }

    @Override
    public Result getRunningProject() {
        List list = processServiceImpl.getProcesss();
        return Result.buildResult(ResultEnum.SUCCESS, list);
    }


}
